﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace FileBrowser
{
    public delegate void UpdateUIMethod  (ulong current,ulong total);

    class Browser
    {
        static void Main(string[] args)
        {
            FInfo extentionBrowser = new FInfo();
            extentionBrowser.RunAndDisplay(true, PrintProgress);
            extentionBrowser.SaveListFromConsole();
        }

        private static int? _lastX = null;
        private static int? _lastY = null;
        private static string _lastPrintedVal = "";

        static void PrintProgress(ulong current, ulong total)
        {
            if (_lastX.HasValue && _lastY.HasValue)
            {
                Console.SetCursorPosition(_lastX.Value, _lastY.Value);
            }

            float percentage = Math.Min(100.0f,(float)current / total * 100);

            String percentStr = String.Format("{0:n2}%", percentage);

            if (percentStr == _lastPrintedVal)
                return;

            _lastPrintedVal = percentStr;


            _lastX = Console.CursorLeft;
            _lastY = Console.CursorTop;
            
            Console.Write(_lastPrintedVal);
        }
    }


    class FInfo
    {
        System.Collections.Specialized.StringCollection log = new System.Collections.Specialized.StringCollection();

        SortedDictionary<String, ExtentionInfo> _aggreagatedInfo = new SortedDictionary<string, ExtentionInfo>();
        
        //List<ExtentionInfo> ExtentionList = new List<ExtentionInfo>();
        
        bool flag = false;
        long totalDataSize = 0;

        public void RunAndDisplay(bool printToConsole, UpdateUIMethod showProgressMethod)
        {
            DriveInfo[] drive = DriveInfo.GetDrives();
            foreach (DriveInfo d in drive)
            {
              
                DirectoryInfo dir = new DirectoryInfo(d.Name);
                if (d.IsReady)
                {
                    ulong processed = 0;
                    ulong totalDrive = (ulong)(d.TotalSize - d.TotalFreeSpace);

                    totalDataSize += d.TotalSize - d.TotalFreeSpace;

                    if (printToConsole)
                    {
                        Console.WriteLine("Disk {0} in process...", d.Name);
                    }

                    GetAllFiles(dir, showProgressMethod,ref processed ,totalDrive );

                    if (printToConsole)
                    {
                        Console.WriteLine("Complete!");
                    }
                }
            }
            sortExtentionList();
            Console.WriteLine(totalDataSize);
            CalcPercentageInList(totalDataSize);
        }

        public void SaveListFromConsole()
        {
            Console.Write("Please input file path: ");
            string path = Console.ReadLine();
            FileInfo file = new FileInfo(path);
            if (file.Exists)
            {
                file.Delete();
            }
            using (StreamWriter sw = file.CreateText())
            {
                sw.WriteLine("Extention|Count|Size|Percentage\n");
                foreach (String ext in _aggreagatedInfo.Keys)
                {
                    _aggreagatedInfo[ext].WriteExtentionInfoToFile(sw);
                }
            }
        
        }

        public void DisplayExtentionListToConsole()
        {
            Console.WriteLine("Extention\t| Count\t| Size\t| Percentage\n");
            foreach(String ext in _aggreagatedInfo.Keys)
            {
                _aggreagatedInfo[ext].PrintExtentionInfoToConsole();
            }
        }
        void GetAllFiles(DirectoryInfo dir, UpdateUIMethod showProgressMethod, ref ulong processed, ulong totalSize)
        {

            FileInfo[] files = null;
            DirectoryInfo[] subDirs = null;
            try
            {
                files = dir.GetFiles("*.*");
            }
            catch (UnauthorizedAccessException e)
            {
                log.Add(e.Message);
            }

            if (files != null)
            {
                foreach (FileInfo f in files)
                {
                    //if (f.Extension != null)
                    //{
                        if (_aggreagatedInfo.ContainsKey(f.Extension))
                        {
                            _aggreagatedInfo[f.Extension].AddItem(f.Length );
                            processed += (ulong) f.Length;
                        }
                        else
                        {
                            ExtentionInfo ei = new ExtentionInfo(f.Extension, f.Length);
                            processed += (ulong) f.Length;
                            _aggreagatedInfo.Add(f.Extension, ei);
                        }

                        if (showProgressMethod != null)
                            showProgressMethod(processed, totalSize);
                    //}
                }
                subDirs = dir.GetDirectories();
                foreach (DirectoryInfo dirf in subDirs)
                {
                    GetAllFiles(dirf, showProgressMethod,ref processed,totalSize);
                }
            }
        }
        void sortExtentionList()
        {
            //ExtentionList.Sort(ExtentionInfo.CompareExtentions);
        }

        void CalcPercentageInList(long totalSize)
        {
            foreach (ExtentionInfo val in _aggreagatedInfo.Values)
            {
                val.CalculatePercentage(totalSize);
            }
        }
    }

    public class ExtentionInfo
    {
        string _extentionName;
        long _count;
        long _size;
        double _percentage;

        public ExtentionInfo()
        {
 
        }

        public ExtentionInfo(string extentionName, long size)
        {
            _extentionName = extentionName;
            _count = 1;
            _size = size;
            _percentage = 0;
        }

        public void CalculatePercentage(long totalSize)
        {
            _percentage = ((double)_size / totalSize) * 100;
            //Console.WriteLine(_percentage);
        }

        public void AddItem(long value)
        {
            _size += value;
            _count++;
        }

        public bool IsEquals(string extention)
        {
            if (_extentionName.Equals(extention)) return true;
            else return false;
        }

        public void PrintExtentionInfoToConsole()
        {
            Console.WriteLine("{0}|{1}|{2}|{3}|\n", _extentionName, _count, _size, _percentage);
        }

        public void WriteExtentionInfoToFile(StreamWriter swrt)
        {
            StringBuilder str = new StringBuilder(_extentionName);
            str.Append("|");
            str.Append(_count);
            str.Append("|");
            str.Append(_size);
            str.Append("|");
            str.Append(_percentage);
            str.Append("\n");
            swrt.Write(str);
        }

        public static int CompareExtentions(ExtentionInfo ei1, ExtentionInfo ei2)
        {
            return ei1._extentionName.CompareTo(ei2._extentionName);
        }
    }
}
